import sys
import time
import random
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout,
    QPushButton, QProgressBar, QLineEdit, QTextEdit, QGridLayout
)
from PySide6.QtCore import QThread, Signal, QObject, QMutex, QWaitCondition


class LogWorker(QObject):
    progress_updated = Signal(int)
    log_received = Signal(str)
    finished = Signal(int)
    paused = Signal(int)

    def __init__(self, worker_id, log_source):
        super().__init__()
        self.worker_id = worker_id
        self.log_source = log_source
        self._is_running = True
        self._is_paused = False
        self._mutex = QMutex()
        self._pause_condition = QWaitCondition()

    def fetch_logs(self):
        try:
            self.log_received.emit(f"Worker {self.worker_id} 开始抓取: {self.log_source}\n")
            
            for progress in range(1, 101):
                self._mutex.lock()
                if not self._is_running:
                    self._mutex.unlock()
                    break
                
                while self._is_paused:
                    self.paused.emit(self.worker_id)
                    self._pause_condition.wait(self._mutex)
                    if not self._is_running:
                        self._mutex.unlock()
                        return
                self._mutex.unlock()
                
                time.sleep(0.1 + random.random() * 0.2)
                self.progress_updated.emit(progress)
                self.log_received.emit(f"[Worker {self.worker_id}] Progress {progress}%\n")
                
            self.finished.emit(self.worker_id)
        except Exception as e:
            self.log_received.emit(f"Worker {self.worker_id} 错误: {str(e)}\n")
            self.finished.emit(self.worker_id)
        finally:
            self.log_received.emit(f"Worker {self.worker_id} 已停止\n")

    def stop(self):
        self._mutex.lock()
        self._is_running = False
        self._pause_condition.wakeAll()
        self._mutex.unlock()

    def pause(self):
        self._mutex.lock()
        self._is_paused = True
        self._mutex.unlock()

    def resume(self):
        self._mutex.lock()
        self._is_paused = False
        self._pause_condition.wakeAll()
        self._mutex.unlock()


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("稳定版日志抓取工具")
        self.setGeometry(300, 300, 800, 600)

        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)

        # 日志显示区域
        self.log_display = QTextEdit()
        self.log_display.setReadOnly(True)
        main_layout.addWidget(self.log_display)

        # 控制区域
        control_layout = QGridLayout()
        main_layout.addLayout(control_layout)

        # 初始化UI组件
        self.inputs = []
        self.start_buttons = []
        self.pause_buttons = []
        self.progress_bars = []
        self.workers = [None] * 4
        self.threads = [None] * 4
        self.task_states = ["stopped"] * 4

        for i in range(4):
            # 创建UI组件
            input_box = QLineEdit(f"http://example.com/logs/{i+1}")
            start_btn = QPushButton(f"开始 {i+1}")
            pause_btn = QPushButton(f"暂停 {i+1}")
            progress_bar = QProgressBar()
            
            # 设置初始状态
            pause_btn.setEnabled(False)
            progress_bar.setRange(0, 100)
            
            # 添加到布局
            control_layout.addWidget(input_box, i, 0)
            control_layout.addWidget(start_btn, i, 1)
            control_layout.addWidget(pause_btn, i, 2)
            control_layout.addWidget(progress_bar, i, 3)
            
            # 保存引用
            self.inputs.append(input_box)
            self.start_buttons.append(start_btn)
            self.pause_buttons.append(pause_btn)
            self.progress_bars.append(progress_bar)
            
            # 连接信号
            start_btn.clicked.connect(lambda _, idx=i: self.toggle_task(idx))
            pause_btn.clicked.connect(lambda _, idx=i: self.toggle_pause(idx))

    def toggle_task(self, idx):
        if self.task_states[idx] == "stopped":
            self.start_task(idx)
        else:
            self.stop_task(idx)

    def start_task(self, idx):
        log_source = self.inputs[idx].text().strip()
        if not log_source:
            self.append_log(f"Worker {idx+1} 需要有效的日志源地址!")
            return

        # 清理之前的线程
        if self.threads[idx] and self.threads[idx].isRunning():
            self.workers[idx].stop()
            self.threads[idx].quit()
            self.threads[idx].wait()

        # 创建新线程
        self.workers[idx] = LogWorker(idx+1, log_source)
        self.threads[idx] = QThread()
        self.workers[idx].moveToThread(self.threads[idx])
        
        # 连接信号
        self.workers[idx].progress_updated.connect(self.progress_bars[idx].setValue)
        self.workers[idx].log_received.connect(self.append_log)
        self.workers[idx].finished.connect(lambda wid: self.task_finished(wid-1))
        self.workers[idx].paused.connect(lambda wid: self.task_paused(wid-1))
        self.threads[idx].started.connect(self.workers[idx].fetch_logs)
        
        # 启动线程
        self.threads[idx].start()
        
        # 更新状态
        self.task_states[idx] = "running"
        self.start_buttons[idx].setText(f"停止 {idx+1}")
        self.pause_buttons[idx].setEnabled(True)
        self.inputs[idx].setEnabled(False)

    def stop_task(self, idx):
        if self.workers[idx]:
            self.append_log(f"Worker {idx+1} 正在停止...")
            self.workers[idx].stop()
            # 不在这里等待线程结束，由finished信号处理

    def task_finished(self, idx):
        """线程安全的任务完成处理"""
        if self.threads[idx]:
            # 确保在主线程执行清理
            if QThread.currentThread() != self.thread():
                self.threads[idx].quit()
                self.threads[idx].wait()
            else:
                self.threads[idx].quit()
                self.threads[idx].wait()
        
        # 重置状态
        self.task_states[idx] = "stopped"
        self.start_buttons[idx].setText(f"开始 {idx+1}")
        self.pause_buttons[idx].setText(f"暂停 {idx+1}")
        self.pause_buttons[idx].setEnabled(False)
        self.inputs[idx].setEnabled(True)
        self.progress_bars[idx].setValue(100)
        
        self.append_log(f"Worker {idx+1} 已完成!")

    def toggle_pause(self, idx):
        if self.task_states[idx] == "running":
            self.pause_task(idx)
        elif self.task_states[idx] == "paused":
            self.resume_task(idx)

    def pause_task(self, idx):
        if self.workers[idx]:
            self.workers[idx].pause()
            self.task_states[idx] = "paused"
            self.pause_buttons[idx].setText(f"继续 {idx+1}")
            self.append_log(f"Worker {idx+1} 已暂停")

    def resume_task(self, idx):
        if self.workers[idx]:
            self.workers[idx].resume()
            self.task_states[idx] = "running"
            self.pause_buttons[idx].setText(f"暂停 {idx+1}")
            self.append_log(f"Worker {idx+1} 已恢复")

    def task_paused(self, idx):
        """线程安全的暂停状态更新"""
        self.task_states[idx] = "paused"
        self.pause_buttons[idx].setText(f"继续 {idx+1}")
        self.append_log(f"Worker {idx+1} 已暂停")

    def append_log(self, text):
        """线程安全的日志追加"""
        self.log_display.append(text)
        self.log_display.verticalScrollBar().setValue(
            self.log_display.verticalScrollBar().maximum()
        )

    def closeEvent(self, event):
        """安全关闭所有线程"""
        for i in range(4):
            if self.workers[i]:
                self.workers[i].stop()
            if self.threads[i] and self.threads[i].isRunning():
                self.threads[i].quit()
                self.threads[i].wait()
        event.accept()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())